use std::collections::HashMap;

use crate::tool_zip::Gzip;
use axum::{
    body::Body,
    http::{HeaderMap, Request, StatusCode},
    response::{IntoResponse, Response},
    Json,
};
use serde::Serialize;
use serde_json::{json, Value};

pub trait HeaderExtend {
    fn gzip(&self) -> bool;
}

impl HeaderExtend for Request<Body> {
    fn gzip(&self) -> bool {
        self.headers()
            .get("g")
            .map_or(true, |v| v.to_str().unwrap_or("") != "0")
    }
}

impl HeaderExtend for HashMap<String, String> {
    fn gzip(&self) -> bool {
        if self.contains_key("g") {
            return self.get("g").unwrap() != "0";
        }
        return true;
    }
}

impl HeaderExtend for HeaderMap {
    fn gzip(&self) -> bool {
        self.get("g")
            .map_or(true, |v| v.to_str().unwrap_or("") != "0")
    }
}

pub fn return_json_res(code: StatusCode, data: ResData, gzip: bool) -> Response<Body> {
    let gzip=false;
    if !gzip {
        let response = Json(data);
        return (code, response).into_response();
    }
    let mut re: HashMap<&str, Value> = HashMap::new();
    re.insert("gzip", json!(true));
    let str = Gzip::compress(data);
    re.insert("data", json!(str));
    return (code, Json(re)).into_response();
}

#[derive(Serialize)]
pub struct ResData {
    pub message: String,
    pub data: Option<Value>,
}

impl ResData {
    pub fn new_msg<T>(msg: T) -> Self
    where
        T: Into<String>,
    {
        Self {
            message: msg.into(),
            data: None,
        }
    }
    pub fn new_data<T>(msg: T, data: Value) -> Self
    where
        T: Into<String>,
    {
        Self {
            message: msg.into(),
            data: Some(data),
        }
    }
    pub fn new_only_data(data: Value) -> Self {
        Self {
            message: "".to_string(),
            data: Some(data),
        }
    }
}
